﻿/*
   Copyright 2012 Dmitry Bratus

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using System.Collections.Generic;
using Flower.Services.Data;
using Flower.Workflow;

namespace Flower.Client
{
    public static class ScriptHelper
    {
        private const string LOCK_SCRIPT = "@Lock";
        private const string UNLOCK_SCRIPT = "@Unlock";
        private const string ENQUEUE_SCRIPT = "@EnqueueMessage";
        private const string ENQUEUE_MULTIPLE_SCRIPT = "@EnqueueMultipleMessages";
        private const string DEQUEUE_SCRIPT = "@DequeueMessage";

        public static double GetJsDate(DateTime dateTime)
        {
            return (dateTime - new DateTime(1970, 1, 1)).TotalMilliseconds;
        }

        public static DateTime FromJsDate(double jsDate)
        {
            return new DateTime(1970, 1, 1) + TimeSpan.FromMilliseconds(jsDate);
        }

        public static LockFailure[] Lock
        (
            IFlowerClient client, 
            IEnumerable<string> resources, 
            string owner, 
            string pid
        )
        {
            var script =
                client
                    .CreateScript()
                    .SetText(LOCK_SCRIPT)
                    .AddParameter("resources", resources)
                    .AddParameter("owner", owner);

            if (pid != null)
            {
                script.AddParameter("pid", pid);
            }

            var result = script.Execute();

            var failedResources = result.Get<IList<string>>("resources");
            var currentOwners = result.Get<IList<string>>("owners");

            if (failedResources == null)
            {
                return new LockFailure[0];
            }

            var lockFailures = new LockFailure[failedResources.Count];

            for (int i = 0; i < failedResources.Count; i++)
            {
                lockFailures[i] =
                    new LockFailure
                    {
                        Resource = failedResources[i],
                        Owner = currentOwners[i]
                    };
            }

            return lockFailures;
        }

        public static void Unlock
        (
            IFlowerClient client, 
            IEnumerable<string> resources, 
            string owner
        )
        {
            client
                .CreateScript()
                .SetText(UNLOCK_SCRIPT)
                .AddParameter("resources", resources)
                .AddParameter("owner", owner)
                .Execute();
        }

        public static bool Enqueue
        (
            IFlowerClient client, 
            string subset,
            Message message,
            string pid
        )
        {
            var script =
                client
                    .CreateScript()
                    .SetText(ENQUEUE_SCRIPT)
                    .AddParameter("subset", subset)
                    .AddParameter("message", message);

            if (pid != null)
            {
                script.AddParameter("pid", pid);
            }

            return script.Execute().Get<bool>("result");
        }

        public static int EnqueueMultiple
        (
            IFlowerClient client,
            string subset,
            IList<DirectoryEntry> messages
        )
        {
            var script =
                client
                    .CreateScript()
                    .SetText(ENQUEUE_MULTIPLE_SCRIPT)
                    .AddParameter("subset", subset)
                    .AddParameter("messages", messages);

            return script.Execute().Get<int>("result");
        }

        public static Message Dequeue
        (
            IFlowerClient client,
            string subset,
            string pid
        )
        {
            var script =
                client
                    .CreateScript()
                    .SetText(DEQUEUE_SCRIPT)
                    .AddParameter("subset", subset);

            if (pid != null)
            {
                script.AddParameter("pid", pid);
            }

            return script.Execute().Get<Message>("message");
        }
    }
}
